package com.anjie.powerproject.controller;

import com.alibaba.fastjson.JSONObject;
import com.anjie.powerproject.common.FillStrategyEnum;
import com.anjie.powerproject.common.Result;
import com.anjie.powerproject.entity.StationInfo;
import com.anjie.powerproject.pojo.dto.AnalyseDTO;
import com.anjie.powerproject.pojo.dto.ProcessCommandDTO;
import com.anjie.powerproject.pojo.dto.ProcessDTO;
import com.anjie.powerproject.service.*;
import com.anjie.powerproject.strategy.pojo.DayWeather;
import com.anjie.powerproject.strategy.service.WeatherForecastService;
import com.anjie.powerproject.strategy.utils.DecimalFormatUtils;
import com.anjie.powerproject.util.CsvData;
import com.anjie.powerproject.util.CsvUtil;
import org.apache.commons.csv.CSVFormat;
import org.apache.tomcat.util.http.fileupload.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.anjie.powerproject.util.GenerateDemoData;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.*;
import java.util.*;

import static com.anjie.powerproject.common.Constants.PYTHON_DIR;

@Controller
public class DemoController {
    @Autowired
    EnergyModelService energyModelService;
    @Autowired
    PreDataDayService preDataDayService;
    @Autowired
    DataDayService dataDayService;
    @Autowired
    ModelService modelService;

    @RequestMapping("/index")
    public String DemoPage1(){
        return "showPage1.html";
    }

    @RequestMapping("/showpage2")
    public String DemoPage2(){
        return "showPage2.html";
    }

    @RequestMapping("/showpage3")
    public String DemoPage3( ){
        return "showPage3.html";
    }

    @RequestMapping("/showpage4")
    public String DemoPage4( ){
        return "showPage4.html";
    }

    @RequestMapping("/showpage5")
    public String DemoPage5( ){
        return "showPage5.html";
    }

    @RequestMapping("/test1")
    public String test1( ){
        return "test1.html";
    }

    @Autowired
    StationInfoService stationInfoService;
    @Autowired
    WeatherForecastService weatherForecastService;

//    @RequestMapping("/Data1")
//    @ResponseBody
//    public String testData(HttpServletRequest request) throws IOException {
//        StationInfo stationInfo = stationInfoService.findStationInfoLimitFirst();
//        String areaCode = stationInfo.getCityCode();
//        // 然后获取前五天加后十天的天气数据（按天算）
//        // 注意这里的地区码应该另外获取
//        List<DayWeather> weathers = null;
//        System.out.println(areaCode);
//        weathers = weatherForecastService.getForecastDayWeatherByAddrCode(areaCode);
//        System.out.println(weathers.size());
//        return null;
//    }



    /**
     * 数据预处理
     */
    @RequestMapping(value = "/energey/demoDataprocess")
    @ResponseBody
    public Result<ProcessDTO> process(HttpServletRequest request, @RequestParam("command") String commandStr, @RequestParam("extraData") MultipartFile[] extraData) {
        try {
            String base = request.getServletContext().getRealPath("WEB-INF/classes/");
            String bases[] = new String[]{base, "src/main/resources/"};
            ProcessCommandDTO commandDTO = JSONObject.parseObject(commandStr, ProcessCommandDTO.class);
            return Result.ok(energyModelService.process(bases, commandDTO, extraData, null, FillStrategyEnum.UNDO));
        } catch (Exception ex) {
//            logger.error("预处理失败 params={} errmsg={}", commandStr, ex.getMessage(), ex);
//            return Result.error(String.format("预处理失败 [%s]", ex.getMessage()));
           return Result.ok();
        }
    }

    @RequestMapping(value = "/energey/demoDataprocess/{model}")
    public Result<ProcessDTO> process(HttpServletRequest request,
                                      @RequestParam("command") String commandStr,
                                      @RequestParam("extraData") MultipartFile[] extraData,
                                      @PathVariable("model") Integer modelId) {
        try {
            String base = request.getServletContext().getRealPath("WEB-INF/classes/");
            String bases[] = new String[]{base, "src/main/resources/"};
            ProcessCommandDTO commandDTO = JSONObject.parseObject(commandStr, ProcessCommandDTO.class);
            return Result.ok(energyModelService.process(bases, commandDTO, extraData, modelId, FillStrategyEnum.FILL_POSITIVE_ONE));
        } catch (Exception ex) {
//            logger.error("预处理失败 params={} errmsg={}", commandStr, ex.getMessage(), ex);
//            return Result.error(String.format("预处理失败 [%s]", ex.getMessage()));
            return Result.ok();
        }
    }


    //计算误差值函数
    private BigDecimal computeAnalyseValue(List<BigDecimal> source, List<BigDecimal> target) {
        assert source.size() == target.size();

//        double sum = 0.0;
//        for (int i = 0; i < target.size(); i++) {
//            sum += target.get(i);
//        }
//        double mean = sum / target.size();
//
//        // R方
//        double scoreTop = 0.0;
//        double scoreBottom = 0.0;
//        for (int i = 0; i < source.size(); i++) {
//            scoreTop += (source.get(i) - target.get(i)) * (source.get(i) - target.get(i));
//            scoreBottom += (target.get(i) - mean) * (target.get(i) - mean);
//        }
//
//        double v = 1 - scoreTop / scoreBottom;
//
//        if (Double.isFinite(v)) {
//            return DecimalFormatUtils.round(1 - scoreTop / scoreBottom, "0.00");
//        }
//
//        return v;

        //平均绝对百分比误差
        BigDecimal num = BigDecimal.valueOf(0.0);
        BigDecimal mae = BigDecimal.valueOf(0.0);
        int a = 0;        //记录有多少天实际值为0的无效数据
        for (int i = 0; i < source.size(); i++) {
//            if (target.get(i) == 0) {
//                a = a + 1;
//                continue;
//            }
            if (target.get(i).compareTo(BigDecimal.valueOf(0.0)) == 0)
            {
                a = a + 1;
                continue;
            }

//            if(Math.abs((source.get(i) / target.get(i)- 1))>1)
//                num++;
//            else
//                num += Math.abs((source.get(i) / target.get(i)) - 1));
            BigDecimal temp = source.get(i).divide(target.get(i),2, RoundingMode.HALF_UP).subtract(BigDecimal.ONE);
            if (temp.abs().compareTo(BigDecimal.ONE) > 0)
                num = num.add(BigDecimal.ONE);
            else
                num = num.add(temp);
        }

        if (target.size()==a)   //每天的实际值都为0的情况
            //return DecimalFormatUtils.round(0.0, "0.00");
            return BigDecimal.valueOf(0.0);

        //mae = num/(target.size()-a);
        mae = num.divide(BigDecimal.valueOf(target.size()-a),2,RoundingMode.HALF_UP);

        //return DecimalFormatUtils.round(1-mae, "0.00");//误差越大，准确率越低
        return  BigDecimal.ONE.subtract(mae);
    }

    //获取两个日期之间的日期集合
    public static List<String> getBetweenDays(String startTime, String endTime) {
        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }

    /**
     * Demo页面生成预测能量
     */
    @RequestMapping(value = "/showpage3/demoModelpredict")
    @ResponseBody
    public Result<AnalyseDTO> predict(String startTime,String endTime,String selectModelName,String modelName,String deviceCode) {
        AnalyseDTO analyseDTO=new AnalyseDTO();
//        List<String> dateList= Arrays.asList("2021-07-01", "2021-07-02", "2021-07-03", "2021-07-04", "2021-07-05", "2021-07-06", "2021-07-07", "2021-07-08", "2021-07-09", "2021-07-10", "2021-07-11", "2021-07-12", "2021-07-13", "2021-07-14", "2021-07-15", "2021-07-16", "2021-07-17", "2021-07-18", "2021-07-19", "2021-07-20", "2021-07-21", "2021-07-22", "2021-07-23", "2021-07-24", "2021-07-25", "2021-07-26", "2021-07-27", "2021-07-28", "2021-07-29", "2021-07-30", "2021-07-31", "2021-08-01", "2021-08-02", "2021-08-03", "2021-08-04", "2021-08-05", "2021-08-06", "2021-08-07", "2021-08-08", "2021-08-09", "2021-08-10", "2021-08-11", "2021-08-12", "2021-08-13", "2021-08-14", "2021-08-15", "2021-08-16", "2021-08-17", "2021-08-18", "2021-08-19", "2021-08-20", "2021-08-21", "2021-08-22", "2021-08-23", "2021-08-24", "2021-08-25", "2021-08-26", "2021-08-27", "2021-08-28", "2021-08-29", "2021-08-30", "2021-08-31", "2021-09-01", "2021-09-02", "2021-09-03", "2021-09-04", "2021-09-05", "2021-09-06", "2021-09-07", "2021-09-08", "2021-09-09", "2021-09-10", "2021-09-11", "2021-09-12", "2021-09-13", "2021-09-14", "2021-09-15", "2021-09-16", "2021-09-17", "2021-09-18", "2021-09-19", "2021-09-20", "2021-09-21", "2021-09-22", "2021-09-23", "2021-09-24", "2021-09-25", "2021-09-26", "2021-09-27", "2021-09-28", "2021-09-29", "2021-09-30");

//        startTime = "2021-07-01";
//        endTime = "2021-09-30";
//        deviceCode="ajdlnt.point56";
        startTime=startTime.replace('/','-');
        endTime=endTime.replace('/','-');
//        System.out.println("startTime："+startTime+"   endTime："+endTime+"   selectModelName："+selectModelName+ "  modelName："+modelName+"   deviceCode："+deviceCode);
        /**
         * startTime 开始时间
         * endTime 结束时间
         * selectModelName 选择的模型名称 原：YC1008_new2
         * modelName 模型名称  YC1008_new1
         * deviceCode  ajdlnt.point56
         */
        Integer selectModelId=modelService.getModelIdByName(selectModelName);
        Integer modelId=modelService.getModelIdByName(modelName);
//        System.out.println(preDataDayService.getPreDataDayValuesById(188,"2021-07-01","2021-09-01"));
//        System.out.println(dataDayService.getDataDayValues(deviceCode,startTime,endTime));

        List<String> dateList=getBetweenDays(startTime,endTime);
        List<BigDecimal> historyList=dataDayService.getDataDayValues(deviceCode,startTime,endTime);
//        List<Double> historyList=Arrays.asList(2840.0, 2551.0, 1940.0, 2825.0, 3516.0, 3674.0, 3471.0, 3160.0, 3850.0, 3487.0, 2935.0, 3180.0, 4715.0, 4478.0, 3997.0, 3888.0, 2370.0, 2770.0, 3827.0, 3506.0, 3840.0, 2585.0, 3407.0, 3542.0, 3573.0, 3637.0, 2270.0, 3888.0, 2124.0, 1820.0, 3564.0, 3424.0, 2904.0, 2790.0, 4365.0, 3414.0, 2969.0, 3519.0, 3533.0, 3737.0, 3466.0, 2621.0, 1805.0, 3480.0, 1993.0, 2379.0, 3618.0, 2586.0, 2525.0, 2035.0, 2942.0, 3266.0, 2561.0, 3443.0, 2504.0, 2615.0, 2504.0, 2706.0, 2454.0, 2241.0, 2316.0, 2901.0, 2784.0, 2839.0, 2469.0, 2123.0, 1642.0, 394.0, 1692.0, 2886.0, 1947.0, 3485.0, 2448.0, 2767.0, 2851.0, 2856.0, 2829.0, 2368.0, 1432.0, 2189.0, 576.0, 427.0, 1589.0, 2728.0, 2377.0, 379.0, 1275.0, 808.0, 1525.0, 1597.0, 328.0, 2235.0);
//        System.out.println("historyList = " + historyList);
        List<BigDecimal> modelList=preDataDayService.getPreDataDayValuesById(modelId,startTime,endTime);
//        List<Double> modelList=Arrays.asList(2827.0, 2851.0, 1119.0, 3018.0, 2928.0, 2958.0, 3601.0, 3204.0, 2920.0, 2652.0, 3269.0, 2882.0, 4464.0, 3924.0, 3833.0, 4248.0, 2908.0, 2921.0, 3743.0, 3321.0, 3786.0, 3970.0, 3997.0, 2801.0, 2563.0, 3371.0, 3444.0, 4248.0, 1900.0, 1466.0, 3131.0, 3380.0, 3193.0, 3216.0, 3717.0, 4051.0, 3213.0, 2724.0, 2756.0, 3049.0, 3589.0, 2580.0, 2624.0, 2733.0, 2852.0, 2689.0, 3402.0, 2490.0, 3058.0, 2303.0, 2506.0, 2709.0, 2365.0, 3492.0, 2845.0, 2431.0, 2827.0, 2710.0, 1933.0, 2615.0, 2650.0, 1858.0, 2800.0, 2690.0, 2943.0, 1316.0, 1292.0, 512.0, 1816.0, 2663.0, 2077.0, 3209.0, 3374.0, 2891.0, 2078.0, 2521.0, 2688.0, 2394.0, 1581.0, 1588.0, 610.0, 287.0, 590.0, 2544.0, 2632.0, 158.0, 294.0, 1269.0, 1295.0, 1645.0, 1338.0, 1549.0);
//        System.out.println("modelList = " + modelList);
        List<BigDecimal> selectedList=preDataDayService.getPreDataDayValuesById(selectModelId,startTime,endTime);
//        List<Double> selectedList=Arrays.asList(2841.0, 2544.0, 1756.0, 2714.0, 3150.0, 3351.0, 3288.0, 3051.0, 3624.0, 3237.0, 3367.0, 3080.0, 4317.0, 4224.0, 3737.0, 3834.0, 2321.0, 2802.0, 3555.0, 3368.0, 3716.0, 2526.0, 3033.0, 3011.0, 2991.0, 3199.0, 2455.0, 3834.0, 2116.0, 1842.0, 3429.0, 3418.0, 2914.0, 2770.0, 4150.0, 3291.0, 2949.0, 3010.0, 2972.0, 3269.0, 3222.0, 2566.0, 1950.0, 3450.0, 1990.0, 2370.0, 3626.0, 2571.0, 2518.0, 2041.0, 2570.0, 3250.0, 2564.0, 3437.0, 2482.0, 2594.0, 2489.0, 2693.0, 2391.0, 2219.0, 2272.0, 2824.0, 2755.0, 2808.0, 2428.0, 1942.0, 1669.0, 428.0, 1787.0, 2880.0, 1961.0, 3486.0, 2445.0, 2742.0, 2729.0, 2749.0, 2766.0, 2395.0, 1580.0, 2200.0, 586.0, 427.0, 1696.0, 2761.0, 2341.0, 727.0, 1121.0, 969.0, 1589.0, 1623.0, 332.0, 2214.0);
//        System.out.println("selectedList = " + selectedList);
        //计算误差值
        BigDecimal[] analyseValues = new BigDecimal[2];
        analyseValues[0] = computeAnalyseValue(modelList, historyList);
        analyseValues[1] = computeAnalyseValue(selectedList, historyList);

        analyseDTO.setAnalyseValue(analyseValues[0]);
        analyseDTO.setAnalyseValues(analyseValues);
        analyseDTO.setAnalyseValues(analyseValues);
        analyseDTO.setDateList(dateList);
        analyseDTO.setHistoryList(historyList);
        analyseDTO.setModelList(modelList);
        analyseDTO.setSelectedList(selectedList);
        analyseDTO.setSelectedModel(selectModelName);

        return Result.ok(analyseDTO);
    }


    @PostMapping("/demo/data")
//    @PostMapping("data")
    @ResponseBody
    public Map<String, Object> getDemoData(float tem1,float tem2,Float hum1,Float hum2,int flag,int peopleNumber,int tianqi){
        Map<String, Object> combine = new HashMap<>();
        float[]  bangong= new float[]{0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,5.0f,28.0f,29.0f,30.0f,29.0f,30.0f,28.0f,29.0f,30.0f,29.0f,30.0f,30.0f,0.0f,0.0f,0.0f,0.0f,0.0f};
        float[] zhaoming = new float[]{0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,35.0f,40.0f,40.0f,40.0f,38.0f,38.0f,37.0f,39.0f,38.0f,36.0f,30.0f,0.0f,0.0f,0.0f,0.0f,0.0f};
        float[] xiaofang = new float[]{8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f};
        float[] other = new float[]{0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,9.5f,8.0f,9.0f,8.5f,0.0f,0.0f,0.0f,0.0f,0.0f};
        float[] guangfu;
        if (tianqi==1){
            guangfu = new float[]{0f,0f,0f,0f,0f,0f,2.9f,12f,21.6f,29.5f,34.7f,37.3f,37.2f,33.2f,23.1f,14f,4.7f,0.3f,0f,0f,0f,0f,0f,0f};
        }else {
            guangfu = new float[]{0f,0f,0f,0f,0f,0f,0f,1.4f,1.9f,5.2f,8.5f,14.8f,11.8f,7.8f,4.3f,1.3f,0f,0f,0f,0f,0f,0f,0f,0f};
        }
        if (flag==0){
            if(hum1==null&&hum2==null) {
                hum1 = 20f;
                hum2 = 30f;
            }
        }else {
            if(hum1==null&&hum2==null) {
                hum1 = 50f;
                hum2 = 70f;
            }
        }
        Map<String, float[]> dataMap = GenerateDemoData.doGenerate(tem1, tem2, hum1, hum2, flag,peopleNumber);
        float[] dianneng = new float[24];
        float[] dianliangs = dataMap.get("dianliang");

        for (int i = 0 ; i < dianliangs.length;i++){
            dianneng[i] = dianliangs[i]-guangfu[i]+bangong[i]+zhaoming[i]+xiaofang[i]+other[i];
            dianneng[i] = new BigDecimal(dianneng[i]).setScale(1,BigDecimal.ROUND_HALF_UP).floatValue();
        }
        combine.put("dianneng",dianneng);
        combine.put("guangfu",guangfu);
        combine.putAll(dataMap);
        return combine;
    }

    //测试holiday.csv文件读取
//    @RequestMapping("/testData1")
//    @ResponseBody
//    public Map<String, Object> testData(HttpServletRequest request) throws IOException {
////    public List<List<String>> testData(HttpServletRequest request) throws IOException {
//
//        String base = request.getServletContext().getRealPath("WEB-INF/classes/static/python/common/holiday.csv");
//
//        String bases[] = new String[]{base,"src/main/resources/"+PYTHON_DIR+"common/holiday.csv"};
//
//        String DemoControllerPath=DemoController.class.getClassLoader().getResource("").getPath();
//        DemoControllerPath+="static/python/common/holiday.csv";
//
//        String s="文件不存在";
//        String fbase = "";
//        for (String b : bases) {
//            File file = new File(b);
//            if (file.exists()) {
//                fbase = b;
//                s="文件存在!!";
//                break;
//            }
//        }
//
//        CsvData csvData = CsvUtil.loadCsv(fbase);
//        for (String header:csvData.getHeader()) {
//            System.out.println(header);
//        }
//        for (List<String> data:csvData.getData()) {
//            for (String data1:data) {
//                System.out.println(data1);
//            }
//        }
//        Map<String, Object> resultMap = new HashMap<>();
//        resultMap.put("base",base);
//        resultMap.put("csvData",csvData.getData());
//        resultMap.put("DemoControllerPath",DemoControllerPath);
//
//        return resultMap;
////        return csvData.getData();
//    }


}
